﻿/*-------------------------------------------------------------------------
* 命名空间: SiliconSelect.Common/CsvHelper
* 类       名: CsvHelper
* 功      能:  Csv文件读取
* 时      间:  2023/6/30 14:43:33
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using WaferSelectV3.Common;
using WaferSelectV3.Extensions;
using WaferSelectV3.Services;

namespace SiliconSelect.Common
{
    public class CsvHelper
    {
        /// <summary>
        /// 将CSV文件转换为List<List<string>>的形式. 一行全部保存到list中,并且去除掉尾部的空格.
        /// </summary>
        /// <param name="csvPath"></param>
        /// <param name="startLine"></param>
        /// <param name="endline"></param>
        /// <param name="hasTitle"></param>
        /// <returns></returns>
        public static List<List<string>> CsvToListStringByStreamReader(string csvPath, int startLine = 1, int endLine = -1, bool hasTitle = false)
        {
            List<List<string>> resList = new List<List<string>>();
            string? strline;
            Encoding encoding = Encoding.GetEncoding("GB2312");
            int rowIndex = 1;
            // 这段代码的作用就是如果这个文件已经被其它的进程打开了,它依然可以以只读的方式打开这个文件.
            using (var fileStream = new FileStream(csvPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (StreamReader reader = new StreamReader(fileStream, encoding))
            {
                while (!string.IsNullOrEmpty(strline = reader.ReadLine()))
                {
                    if (rowIndex < startLine)
                    {
                        rowIndex++;
                        continue;
                    }
                    if (rowIndex >= endLine && endLine != -1)
                    {
                        break;
                    }
                    string pattern = @",(?=(?:[^""]*""[^""]*"")*[^""]*$)";
                    // 去除掉空字符串
                    List<string> lineRes = Regex.Split(strline, pattern).
                        Where(s => !string.IsNullOrEmpty(s)).ToList();
                    resList.Add(lineRes);
                    rowIndex++;
                }
            }
            return resList;
        }

        /// <summary>
        /// 将CSV文件转换为DataTable (文件流的方式),可以指定开始行,-1表示末尾.
        /// hasTitle是否具有标题,默认是没有标题的.
        /// </summary>
        /// <param name="csvPath"></param>
        /// <param name="startLine">从第一行开始(包括第一行)</param>
        /// <param name="endLine">到哪一行结束(不包括最后一行)</param>
        /// <param name="hasTitle"></param>
        /// <returns></returns>
        public static DataTable CsvToDataTableByStreamReader(string csvPath, int startLine = 1, int endLine = -1, bool hasTitle = true)
        {
            DataTable csvDt = new DataTable("csv");
            int intColCount = 0;
            DataColumn column;
            DataRow row;
            string? strline;
            string[] lineArray;
            Encoding encoding = Encoding.GetEncoding("GB2312");
            int rowIndex = 1;
            // 这段代码的作用就是如果这个文件已经被其它进程打开了,它依然可以以只读的方式打开这个文件.
            using (var fileStream = new FileStream(csvPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (StreamReader reader = new StreamReader(fileStream, encoding))
            {
                while (!string.IsNullOrEmpty(strline = reader.ReadLine()))
                {
                    if (rowIndex < startLine)
                    {
                        rowIndex++;
                        continue;
                    }
                    if (rowIndex >= endLine && endLine != -1)
                    {
                        break;
                    }
                    string pattern = @",(?=(?:[^""]*""[^""]*"")*[^""]*$)";
                    // 去除掉空字符串
                    lineArray = Regex.Split(strline, pattern).
                        Where(s => !string.IsNullOrEmpty(s)).ToArray();

                    if (hasTitle)
                    {
                        hasTitle = false;
                        intColCount = lineArray.Length;
                        for (int i = 0; i < intColCount; i++)
                        {
                            column = new DataColumn(lineArray[i]);
                            csvDt.Columns.Add(column);
                        }
                        rowIndex++;
                        continue;
                    }

                    row = csvDt.NewRow();
                    for (int i = 0; i < intColCount; i++)
                    {
                        if (i < lineArray.Length)
                        {
                            row[i] = lineArray[i];
                        }
                        else
                        {
                            row[i] = "";
                        }
                    }
                    csvDt.Rows.Add(row);
                    rowIndex++;
                }
            }
            return csvDt;
        }


        /// <summary>
        /// 多行写入CSV文件
        /// </summary>
        /// <param name="filePathName"></param>
        /// <param name="data"></param>
        /// <param name="append"></param>
        public static void WriteToCsvMultiLines(string filePathName, List<List<string>> data, bool append = true)
        {
            try
            {
                File.SetAttributes(filePathName, FileAttributes.Normal);
                using (StreamWriter fileWriter = new StreamWriter(filePathName, append, Encoding.Default))
                {
                    foreach (List<string> str in data)
                    {
                        fileWriter.WriteLine(string.Join(",", str));
                    }
                }
                File.SetAttributes(filePathName, FileAttributes.ReadOnly);
            }
            catch (Exception ex)
            {
                LoggerHelper.WriteLogMain(ex.GetFullException(), LogType.Exception);
            }
        }

        /// <summary>
        /// 单行写入CSV文件
        /// </summary>
        /// <param name="filePathName"></param>
        /// <param name="data"></param>
        /// <param name="append"></param>
        public static void WriteToCsvSingleLine(string filePathName, List<string> singleData, bool append = true)
        {
            try
            {
                File.SetAttributes(filePathName, FileAttributes.Normal);
                using (StreamWriter fileWriter = new StreamWriter(filePathName, append, Encoding.UTF8))
                {
                    fileWriter.WriteLine(string.Join(",", singleData));
                }
                File.SetAttributes(filePathName, FileAttributes.ReadOnly);
            }
            catch (Exception ex)
            {
                LoggerHelper.WriteLogMain(ex.GetFullException(), LogType.Exception);
            }
        }


        public static List<int> strIndex = new List<int>()
        {
            0,1,2,3,4,5,6,7,8,9,10,11,12
        };

        public static List<int> HasOrNot = new List<int>()
        {
            46,49,52,54,56,58,68,72,73,74,78,79,80,83,86,88,91,94
        };

        public static List<int> YesOrNo = new List<int>()
        {
            62,71,77
        };
        public static DataResult DataTableToCsv(DataTable vContent, string filePath)
        {
            DataResult result = new DataResult();
            StringBuilder sCsvContent = new StringBuilder();
            foreach (var title in ConstantProvider.SummaryTitle)
            {
                sCsvContent.Append(title);
                sCsvContent.Append(",");
            }
            sCsvContent.Append("\r\n");
            //sCsvContent.Append(GlobalValues.SummaryTitle.ToString());
            File.SetAttributes(filePath, FileAttributes.Normal);
            try
            {
                //数据
                foreach (DataRow row in vContent.Rows)
                {
                    for (int i = 0; i < vContent.Columns.Count; i++)
                    {
                        sCsvContent.Append(row[i].ToString()!.Trim());
                        sCsvContent.Append(i == vContent.Columns.Count - 1 ? "\r\n" : ",");
                    }
                }
                File.WriteAllText(filePath, sCsvContent.ToString(), Encoding.UTF8);
                result.State = true;
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            finally
            {
                File.SetAttributes(filePath, FileAttributes.ReadOnly);
            }
            return result;
        }

        /// <summary>
        /// 根据原始字符串获取其保存为CSV的数值形式
        /// </summary>
        /// <param name="original"></param>`
        /// <returns></returns>
        public static string GetNumberValForCsv(string original)
        {
            return string.IsNullOrEmpty(original) ? original : $"={original}";
        }
    }
}
